﻿// CWndRAN.cpp: 实现文件
//

#include "pch.h"
#include "GameHacker.h"
#include "CWndRAN.h"
#include "afxdialogex.h"


// CWndRAN 对话框

CWndRAN* _wndRAN = nullptr;

IMPLEMENT_DYNAMIC(CWndRAN, CDialogEx)

CWndRAN::CWndRAN(CWnd* pParent /*=nullptr*/)
	: CDialogEx(IDD_RAN, pParent)
{
	_wndRAN = this;
}

CWndRAN::~CWndRAN()
{
}

void CWndRAN::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_TREE1, mTree);
	DDX_Control(pDX, IDC_DATA_LIST, m_lstData);
}

CObjContext* CWndRAN::GetObjPtr(HTREEITEM h)
{
	PTREE_DATA val = (PTREE_DATA)mTree.GetItemData(h);
	if (val) {
		CObjContext* obj = (CObjContext*)val->lpData;
		return obj;
	}
	return nullptr;
}


BEGIN_MESSAGE_MAP(CWndRAN, CDialogEx)
	ON_NOTIFY(NM_RCLICK, IDC_TREE1, &CWndRAN::OnNMRClickTree1)
	ON_COMMAND(ID_32775, &CWndRAN::OnLoadGame)
	ON_COMMAND(ID_32776, &CWndRAN::OnAddClass)
	ON_COMMAND(ID_32786, &CWndRAN::OnDeleteClass)
	ON_COMMAND(ID_32787, &CWndRAN::OnSetClass)
	ON_COMMAND(ID_32785, &CWndRAN::OnAnlyClass)
	ON_NOTIFY(NM_CUSTOMDRAW, IDC_DATA_LIST, &CWndRAN::OnNMCustomdrawDataList)
	ON_NOTIFY(NM_RCLICK, IDC_DATA_LIST, &CWndRAN::OnNMRClickDataList)
	ON_COMMAND(ID_32789, &CWndRAN::OnSetGIDUNICODE)
	ON_COMMAND(ID_32790, &CWndRAN::OnSetGIDASCII)
	ON_COMMAND(ID_32791, &CWndRAN::OnSetGID8)
	ON_COMMAND(ID_32792, &CWndRAN::OnSetGID4)
	ON_COMMAND(ID_32793, &CWndRAN::OnSetGID2)
	ON_COMMAND(ID_32794, &CWndRAN::OnSetGID1)
	ON_COMMAND(ID_32795, &CWndRAN::OnSetGIDP)
	ON_NOTIFY(NM_DBLCLK, IDC_DATA_LIST, &CWndRAN::OnNMDblclkDataList)
	ON_COMMAND(ID_32788, &CWndRAN::OnSaveOBJ)
	ON_COMMAND(ID_32796, &CWndRAN::OnAddFunc)
END_MESSAGE_MAP()


// CWndRAN 消息处理程序


void CWndRAN::OnNMRClickTree1(NMHDR* pNMHDR, LRESULT* pResult)
{
	*pResult = 0;
	// TODO: 在此添加控件通知处理程序代码


	DWORD dwMenuId = 1;
	if (hProcess) {
		unsigned int nFlags = 0;
		CPoint point(GetMessagePos());
		mTree.ScreenToClient(&point);
		HTREEITEM hItem = mTree.HitTest(point, &nFlags);
		mTree.SetFocus();
		mTree.SelectItem(hItem);

		auto hSel = mTree.GetSelectedItem();
		if (hSel) {
			PTREE_DATA val = (PTREE_DATA)mTree.GetItemData(hSel);
			if (val)
				dwMenuId = val->dwMenuId;
			else dwMenuId = 0;
		}
		else dwMenuId = 2;
	}

	DWORD dwPos = GetMessagePos();
	CPoint point(LOWORD(dwPos), HIWORD(dwPos));//记录鼠标位置
	CMenu menu;
	menu.LoadMenuW(IDR_MENU1);
	CMenu* popMenu = menu.GetSubMenu(dwMenuId);
	popMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, this); //弹出右键菜单
	
}

void _stdcall ReadData(HWND hWnd, UINT uEvent, UINT_PTR uintPtr , DWORD dWord) {
	if (!_wndRAN->hProcess) return;
	if (!_wndRAN->m_CurObj) return;
	if (!_wndRAN->m_CurObj->UpdateData(_wndRAN->hProcess)) {
		AfxMessageBox(L"读取内存失败!请检查是否具有管理员权限,或者内存地址是否可读!");
	}

	//显示数据
	_wndRAN->ShowMemContext();
}

BOOL CWndRAN::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// TODO:  在此添加额外的初始化
		//设置listbox的样式
	long lStyle;
	lStyle = GetWindowLongPtr(m_lstData.m_hWnd, GWL_STYLE);
	lStyle |= LVS_REPORT;
	SetWindowLongPtr(m_lstData.m_hWnd, GWL_STYLE, lStyle);
	lStyle = m_lstData.GetExtendedStyle();
	lStyle |= LVS_EX_FULLROWSELECT;//一次选中一整行
	lStyle |= LVS_EX_GRIDLINES;//设置显示格子线
	m_lstData.SetExtendedStyle(lStyle);

	m_lstData.InsertColumn(0, L"内存地址", 0, 100);
	m_lstData.InsertColumn(1, L"偏移", 0, 100);
	m_lstData.InsertColumn(2, L"类型", 0, 100);
	m_lstData.InsertColumn(3, L"名称", 0, 100);
	m_lstData.InsertColumn(4, L"值", 0, 100);
	m_lstData.InsertColumn(5, L"注释", 0, 100);
	m_lstData.InsertColumn(6, L"显示类型", 0, 200);

	InitDataTypeTable();
	::SetTimer(m_lstData.m_hWnd, 10002, 5000, ReadData);

	return TRUE;  // return TRUE unless you set the focus to a control
				  // 异常: OCX 属性页应返回 FALSE
}


void CWndRAN::OnLoadGame()
{
	// TODO: 在此添加命令处理程序代码
	if (wndProcess.DoModal() == IDOK) {
		hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, wndProcess.m_dwPid);
		if (hProcess) {
			auto troot = InsertItemEx(wndProcess.m_Exe, 2, NULL);
			InsertItemEx(L"公共数据", 3, NULL, troot);
			InsertItemEx(L"公共函数", 4, NULL, troot);
			InsertItemEx(L"HOOK分析", 5, NULL, troot);

			m_wAnlyData = m_wAnlyPath + wndProcess.m_Exe;
			if (!PathIsDirectory(m_wAnlyPath))
				CreateDirectory(m_wAnlyPath, NULL); //创建RAN文件夹

			if (!PathIsDirectory(m_wAnlyData)) {
				if (!CreateDirectory(m_wAnlyData, NULL)) {
					AfxMessageBox(L"创建文件夹失败！");
					return;
				}
			}
			
			//ini
			WIN32_FIND_DATA file;
			auto hFind = FindFirstFile(m_wAnlyData+L"\\*.ini", &file);
			while (hFind != INVALID_HANDLE_VALUE) {
				CString name = file.cFileName;
				name.Replace(L".ini", L"");
				CObjContext* obj = new CObjContext(m_wAnlyData, name);
				AddObjTree(obj);

				if (!FindNextFile(hFind, &file)) {
					FindClose(hFind);
					break;
				}
			}
		}
		else {
			AfxMessageBox(L"加载游戏失败！");
		}
	}
}

void CWndRAN::SetPath(CString& path)
{
	m_wAnlyPath = path + L"\\RAN\\";
}

HTREEITEM CWndRAN::InsertItemEx(const wchar_t* wcsTxt, DWORD dwMenuId, LPVOID lpData, HTREEITEM hTreeItem)
{
	auto _rt = mTree.InsertItem(wcsTxt, hTreeItem);
	PTREE_DATA pTreeData = new TREE_DATA{ dwMenuId, (DWORD_PTR)lpData };
	mTree.SetItemData(_rt, (DWORD_PTR)pTreeData);
	return _rt;
}

void CWndRAN::DeleteItemEx(HTREEITEM hTreeItem)
{
	PTREE_DATA val = (PTREE_DATA)mTree.GetItemData(hTreeItem);
	if (val)
		delete val;
}

HTREEITEM CWndRAN::GetFirstItem(HTREEITEM hTreeItem)
{
	HTREEITEM hFirstItem;
	do {
		hFirstItem = hTreeItem;
		hTreeItem = mTree.GetParentItem(hFirstItem);
	} while (hTreeItem);
	
	return hFirstItem;
}


void CWndRAN::OnAddClass()
{
	if (!hProcess) return;

	if (wndAddClass.DoModal() == IDOK) {
		auto h = mTree.GetRootItem();
		while (h) {
			h = mTree.GetNextSiblingItem(h);
			if (mTree.GetItemText(h) == wndAddClass.m_sName) {
				AfxMessageBox(L"请勿重复添加!");
				return;
			}
		}
		CObjContext* obj = new CObjContext(m_wAnlyData, wndAddClass.m_sName, wndAddClass.m_sAddress, wndAddClass.m_dwSize, wndAddClass.m_sNote);
		AddObjTree(obj);
	}
}


void CWndRAN::OnDeleteClass()
{
	auto hSel = mTree.GetSelectedItem();
	auto hRoot = mTree.GetRootItem();
	if (hRoot == hSel) return;
	auto h = GetFirstItem(hSel);

	PTREE_DATA val = (PTREE_DATA)mTree.GetItemData(h);
	if (val) {
		CObjContext* p = (CObjContext*)val->lpData;
		if (p) {
			p->DeleteIniFile();
		}
	}
	DeleteItemEx(h);
	mTree.DeleteItem(h);
}


void CWndRAN::OnSetClass()
{
	auto hSel = mTree.GetSelectedItem();
	auto hRoot = mTree.GetRootItem();
	if (hRoot == hSel) return;
	auto h = GetFirstItem(hSel);

	if (h) {
		auto obj = GetObjPtr(h);
		if (obj == nullptr) return;
		wndAddClass.m_sAddress = obj->GetAddress();
		wndAddClass.m_sNote = obj->GetNote();
		wndAddClass.m_dwSize = obj->GetSize();
		wndAddClass.m_sName = mTree.GetItemText(h);
		if (wndAddClass.DoModal() == IDOK) {
			obj->Set(wndAddClass.m_sName, wndAddClass.m_sAddress, wndAddClass.m_dwSize, wndAddClass.m_sNote);
			SetObjTree(h, obj);
		}
	}
}

HTREEITEM CWndRAN::AddObjTree(CObjContext* obj)
{
	auto hRoot = InsertItemEx(obj->GetName(), 6, obj, TVI_ROOT);

	auto hBase = InsertItemEx(L"基本信息", 6, NULL, hRoot);
	CString sAddress;
	sAddress.Format(L"内存地址:%s", obj->GetAddress().GetBuffer());
	InsertItemEx(sAddress, 6, NULL, hBase);
	CString sSize;
	sSize.Format(L"对象大小:%d", obj->GetSize());
	InsertItemEx(sSize, 6, NULL, hBase);
	CString sNote;
	sNote.Format(L"注释:%s", obj->GetNote().GetBuffer());
	InsertItemEx(sNote, 6, NULL, hBase);

	InsertItemEx(L"成员变量", 6, NULL, hRoot);
	InsertItemEx(L"成员函数", 8, NULL, hRoot);
	
	return hRoot;
}

void CWndRAN::SetObjTree(HTREEITEM h, CObjContext* obj)
{
	mTree.SetItemText(h, obj->GetName());
	auto hBase = mTree.GetChildItem(h);
	
	auto hBaseSon = mTree.GetChildItem(hBase);
	CString sAddress;
	sAddress.Format(L"内存地址:%s", obj->GetAddress().GetBuffer());
	mTree.SetItemText(hBaseSon, sAddress);
	
	hBaseSon = mTree.GetNextSiblingItem(hBaseSon);
	CString sSize;
	sSize.Format(L"对象大小:%d", obj->GetSize());
	mTree.SetItemText(hBaseSon, sSize);

	hBaseSon = mTree.GetNextSiblingItem(hBaseSon);
	CString sNote;
	sNote.Format(L"注释:%s", obj->GetNote().GetBuffer());
	mTree.SetItemText(hBaseSon, sNote);
}


void CWndRAN::OnAnlyClass()
{
	auto hSel = mTree.GetSelectedItem();
	auto hRoot = mTree.GetRootItem();
	if (hRoot == hSel) return;
	auto h = GetFirstItem(hSel);

	if (h) {
		auto obj = GetObjPtr(h);
		if (obj) {
			if (m_CurObj != obj)
				m_lstData.DeleteAllItems();
			m_CurObj = obj;
			ReadData(0, 0, 10002, 0);
		}	
	}
}

void CWndRAN::ShowMemContext()
{
	if (!m_CurObj) return;
	m_lstData.SetRedraw(false);

	//CurObj->MemContext->
	int iCount = 0;
	int lstCount = m_lstData.GetItemCount();

	LPVOID _address = m_CurObj->GetMemAddress();
	PCMemContext _mcontext = m_CurObj->pMemContext;

	while (_mcontext) {
		int lenth = _mcontext->nLen;
		for (int i = 0; i < lenth; i++) {
			DWORD_PTR adr = (DWORD_PTR)_address + _mcontext->offset;
			CString txt, offset, name, val, oldval;
			txt.Format(L"%x", adr + i * _mcontext->Type->dwSize);
			offset.Format(L"+0x%x", _mcontext->offset + i * _mcontext->Type->dwSize);

			int iLen = lenth;
			if (_mcontext->Extend) iLen = i;
			
			
			if (lenth > 1)
				name.Format(L"%s[%d]", _mcontext->sName.GetBuffer(), iLen);
			else
				name.Format(L"%s", _mcontext->sName.GetBuffer());
			
			if (!_mcontext->Extend) lenth = 1; //非扩展的截断

			if (!lstCount) {
				m_lstData.InsertItem(iCount, txt);
				PLIST_DATA lstData = new LIST_DATA{ 0, _mcontext, (DWORD)i };
				m_lstData.SetItemData(iCount, (DWORD_PTR)lstData);
			}
				
			m_lstData.SetItemText(iCount, 0, txt);
			m_lstData.SetItemText(iCount, 1, offset);
			m_lstData.SetItemText(iCount, 2, _mcontext->Type->sName);
			m_lstData.SetItemText(iCount, 3, name);

			val = m_CurObj->ReadValue(_mcontext, i);
			oldval = m_lstData.GetItemText(iCount, 4);
			DWORD exId = !(val == oldval);
			PLIST_DATA p = (PLIST_DATA)m_lstData.GetItemData(iCount);
			if (p) p->ExId = exId;

			m_lstData.SetItemText(iCount, 4, val);
			m_lstData.SetItemText(iCount, 5, _mcontext->sNote);

			val = m_CurObj->ReadGValue(_mcontext, i);
			m_lstData.SetItemText(iCount++, 6, val);
		}
		_mcontext = _mcontext->Next;
	}
	m_lstData.SetRedraw(true);
}


HTREEITEM CWndRAN::GetSonItem(HTREEITEM h, int index)
{
	auto t = mTree.GetChildItem(h);
	for (int i = 0; i < index; i++) {
		t = mTree.GetNextSiblingItem(t);
		if (!t) return nullptr;
	}
	return t;
}



void CWndRAN::OnNMCustomdrawDataList(NMHDR* pNMHDR, LRESULT* pResult)
{
	LPNMCUSTOMDRAW pNMCD = reinterpret_cast<LPNMCUSTOMDRAW>(pNMHDR);
	// TODO: 在此添加控件通知处理程序代码
	*pResult = 0;

	NMLVCUSTOMDRAW* lp = (NMLVCUSTOMDRAW*)pNMHDR;
	auto& nmcd = lp->nmcd;
	switch (nmcd.dwDrawStage) {
	case CDDS_PREPAINT:
		*pResult = CDRF_NOTIFYITEMDRAW;
		break;
	case CDDS_ITEMPREPAINT:
	{
		PLIST_DATA p = (PLIST_DATA)m_lstData.GetItemData(nmcd.dwItemSpec);
		if (p) {
			COLORREF colors[]{ RGB(0,0,0), RGB(255,0,0) };
			lp->clrText = colors[p->ExId];
		}
		*pResult = CDRF_DODEFAULT;
	}
	break;
	}
}


void CWndRAN::OnNMRClickDataList(NMHDR* pNMHDR, LRESULT* pResult)
{
	LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
	// TODO: 在此添加控件通知处理程序代码
	*pResult = 0;

	if (m_CurObj) {
		DWORD dwPos = GetMessagePos();
		CPoint point(LOWORD(dwPos), HIWORD(dwPos));//记录鼠标位置
		CMenu menu;
		menu.LoadMenuW(IDR_MENU1);
		CMenu* popMenu = menu.GetSubMenu(7);
		popMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, this); //弹出右键菜单
	}
}


void CWndRAN::OnSetGIDUNICODE()
{
	if (m_CurObj) m_CurObj->SetGId(0);
	ReadData(0, 0, 10002, 0);
}


void CWndRAN::OnSetGIDASCII()
{
	if (m_CurObj) m_CurObj->SetGId(1);
	ReadData(0, 0, 10002, 0);
}


void CWndRAN::OnSetGID8()
{
	if (m_CurObj) m_CurObj->SetGId(2);
	ReadData(0, 0, 10002, 0);
}


void CWndRAN::OnSetGID4()
{
	if (m_CurObj) m_CurObj->SetGId(3);
	ReadData(0, 0, 10002, 0);
}


void CWndRAN::OnSetGID2()
{
	if (m_CurObj) m_CurObj->SetGId(4);
	ReadData(0, 0, 10002, 0);
}


void CWndRAN::OnSetGID1()
{
	if (m_CurObj) m_CurObj->SetGId(5);
	ReadData(0, 0, 10002, 0);
}


void CWndRAN::OnSetGIDP()
{
	if (m_CurObj) m_CurObj->SetGId(6);
	ReadData(0, 0, 10002, 0);
}


void CWndRAN::OnNMDblclkDataList(NMHDR* pNMHDR, LRESULT* pResult)
{
	LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
	// TODO: 在此添加控件通知处理程序代码
	*pResult = 0;

	if (pNMItemActivate->iItem != 1) {
		PLIST_DATA p = (PLIST_DATA)m_lstData.GetItemData(pNMItemActivate->iItem);
		if (p) {
			wndEditMContext.sAddress = m_lstData.GetItemText(pNMItemActivate->iItem, 0);
			wndEditMContext.sOffset = m_lstData.GetItemText(pNMItemActivate->iItem, 1);
			wndEditMContext.sName = p->pMContext->sName;
			wndEditMContext.sNote = p->pMContext->sNote;
			wndEditMContext.wCount = p->index ? 1 : p->pMContext->nLen;
			wndEditMContext.type_id = p->pMContext->type_id;
			wndEditMContext.sData = m_CurObj->ReadGAllValue(p->pMContext, p->index);
			if (wndEditMContext.DoModal() == IDOK) {
				//进入编辑页面
				int nRet = m_CurObj->SetMemContext(p->pMContext, wndEditMContext.sName, wndEditMContext.sNote, wndEditMContext.wCount,
					wndEditMContext.type_id, p->index);
				if (nRet == -1) {
					AfxMessageBox(L"内存空间不足!");
				}
				else {
					m_lstData.DeleteAllItems();
					ReadData(0, 0, 10002, 0);
				}
			}
		}
	}
}


void CWndRAN::OnSaveOBJ()
{
	auto hSel = mTree.GetSelectedItem();
	auto hRoot = mTree.GetRootItem();
	if (hRoot == hSel) return;
	auto h = GetFirstItem(hSel);

	if (h) {
		auto obj = GetObjPtr(h);
		obj->CreateCPP();
	}
}


void CWndRAN::OnAddFunc()
{
	auto hSel = mTree.GetSelectedItem();
	auto hRoot = mTree.GetRootItem();
	if (hRoot == hSel) return;
	auto h = GetFirstItem(hSel);

	if (h) {
		auto obj = GetObjPtr(h);
		if (obj) {
			wndAddFunc.Init(nullptr, obj);
			if (wndAddFunc.DoModal() == IDOK) {
				auto p = wndAddFunc.pFuncReturn;
				auto pp = p->Params;
				CString val, txtP;
				while (pp) {
					txtP = L"," + txtP + pp->sType + L" " + pp->sName;
					pp = pp->Next;
				}
				if (!txtP.IsEmpty()) txtP.Delete(0, 1);
				val.Format(L"%s %s(%s);", p->sType, p->sName, txtP);
				auto t = GetSonItem(h, 2);
				InsertItemEx(val, 8, NULL, t);
			}
		}
	}
}
